#include "fsl_dma.h"
#include "fsl_spi_dma.h"
#include "fsl_gpio.h"
#include "fsl_debug_console.h"
#include "fsl_pint.h"
#define ADS_CS_PORT 0U
#define ADS_CS_PIN 4U

#define ADS_RESET_PORT 0U
#define ADS_RESET_PIN 20U

#define ADS_START_PORT 0U
#define ADS_START_PIN 13U

#define ADS_DRDY_PORT 0U
#define ADS_DRDY_PORT_PIN 14U

#define ADS_SPI_MASTER SPI3
#define ADS_SPI_MASTER_IRQ FLEXCOMM3_IRQn
#define ADS_SPI_MASTER_CLK_SRC kCLOCK_Flexcomm3
#define ADS_SPI_MASTER_CLK_FREQ CLOCK_GetFlexCommClkFreq(3U)
//#define ADS_SPI_MASTER_CLK_FREQ CLOCK_GetHsLspiClkFreq()
#define ADS_SPI_SSEL 1
#define ADS_SPI_SPOL kSPI_SpolActiveAllLow

//add dma driver
#define ADS_DMA                     DMA1
#define ADS_SPI_MASTER_RX_CHANNEL   8
#define ADS_SPI_MASTER_TX_CHANNEL   9

static spi_dma_handle_t ads_masterHandle;
static dma_handle_t ads_masterTxHandle;
static dma_handle_t ads_masterRxHandle;

static volatile bool ads_isTransferCompleted = false;
static spi_master_config_t userConfig = {0};
static uint8_t dma_init_flag = 0;
static spi_transfer_t masterXfer;

#ifndef _BOOTLOADER

static void ads_spi_init1(void)
{
	SPI_MasterGetDefaultConfig(&userConfig);
	userConfig.polarity = kSPI_ClockPolarityActiveHigh;
	userConfig.phase = kSPI_ClockPhaseSecondEdge;
    
    userConfig.baudRate_Bps = 12000000U;
    userConfig.sselNum = (spi_ssel_t)ADS_SPI_SSEL;
    userConfig.sselPol = (spi_spol_t)ADS_SPI_SPOL;
    SPI_MasterInit(ADS_SPI_MASTER, &userConfig, ADS_SPI_MASTER_CLK_FREQ);
}


static void ads_MasterDMASetup(void)
{
    /* DMA init */
    DMA_Init(ADS_DMA);
    /* Configure the DMA channel,priority and handle. */
    DMA_EnableChannel(ADS_DMA, ADS_SPI_MASTER_TX_CHANNEL);
    DMA_EnableChannel(ADS_DMA, ADS_SPI_MASTER_RX_CHANNEL);
    DMA_SetChannelPriority(ADS_DMA, ADS_SPI_MASTER_TX_CHANNEL, kDMA_ChannelPriority1);
    DMA_SetChannelPriority(ADS_DMA, ADS_SPI_MASTER_RX_CHANNEL, kDMA_ChannelPriority2);
    DMA_CreateHandle(&ads_masterTxHandle, ADS_DMA, ADS_SPI_MASTER_TX_CHANNEL);
    DMA_CreateHandle(&ads_masterRxHandle, ADS_DMA, ADS_SPI_MASTER_RX_CHANNEL);
}


static void SPI_MasterUserCallback(SPI_Type *base, spi_dma_handle_t *handle, status_t status, void *userData)
{
    if (status == kStatus_Success)
    {
        ads_isTransferCompleted = true;
    }
}


static void ads_spi_dma_init(void)
{    
    //ads_spi_init1();
    ads_MasterDMASetup();
    SPI_MasterTransferCreateHandleDMA(ADS_SPI_MASTER, &ads_masterHandle, SPI_MasterUserCallback, NULL, &ads_masterTxHandle,
                                      &ads_masterRxHandle);
}



void ecg_spi_dma_read_buf(uint8_t *t_data,uint8_t *r_data,uint32_t rx_len)
{
    if(dma_init_flag == 0)
    {
        PRINTF("ads_spi_dma_init\r\n ");
        ads_spi_dma_init();
        dma_init_flag = 1;
    }
//    PRINTF("++++0++++++\r\n ");
	ads_isTransferCompleted=false;

    /* Start master transfer */
    masterXfer.txData      = (uint8_t *)t_data;
    masterXfer.rxData      = (uint8_t *)r_data;
    masterXfer.dataSize    = rx_len;
    //kSPI_FrameAssert or kSPI_FrameDelay
    masterXfer.configFlags = kSPI_FrameAssert;
	
    if (kStatus_Success != SPI_MasterTransferDMA(ADS_SPI_MASTER, &ads_masterHandle, &masterXfer))
    {
        PRINTF("There is an error when start SPI_MasterTransferDMA \r\n ");
    }
//    PRINTF("++++1++++++\r\n ");
	while (!ads_isTransferCompleted)
    {
		//FeedWDI();
    }
    PRINTF("++++2++++++\r\n ");
}
#endif

void ecg_DR_event_enable(void)
{
	PINT_EnableCallback(PINT);
    //PRINTF("%s\r\n",__FUNCTION__);
}


void ecg_DR_event_disable(void)
{
	PINT_DisableCallback(PINT);
    //PRINTF("%s\r\n",__FUNCTION__);
}


void Init_Ecg_PINT(pint_cb_t callback)
{
	/* Initialize PINT */
	PINT_Init(PINT);

	/* Setup Pin Interrupt 0 for rising edge */
	PINT_PinInterruptConfig(PINT, kPINT_PinInt0, kPINT_PinIntEnableFallEdge, callback);
	PINT_EnableCallbackByIndex(PINT, kPINT_PinInt0);
    PRINTF("%s\r\n",__FUNCTION__);
}

void Init_Ecg_Gpio(void)
{
	ecg_DR_event_disable();

	// cs output high
	gpio_pin_config_t cs_config = {
		kGPIO_DigitalOutput,
		0,
	};
	GPIO_PortInit(GPIO, ADS_CS_PORT);
	GPIO_PinInit(GPIO, ADS_CS_PORT, ADS_CS_PIN, &cs_config);
	GPIO_PinWrite(GPIO, ADS_CS_PORT, ADS_CS_PIN, 1);

	// reset output high
	gpio_pin_config_t reset_config = {
		kGPIO_DigitalOutput,
		0,
	};
	GPIO_PortInit(GPIO, ADS_RESET_PORT);
	GPIO_PinInit(GPIO, ADS_RESET_PORT, ADS_RESET_PIN, &reset_config);
	GPIO_PinWrite(GPIO, ADS_RESET_PORT, ADS_RESET_PIN, 1);
    
	// start output high
	gpio_pin_config_t start_config = {
		kGPIO_DigitalOutput,
		0,
	};
	GPIO_PortInit(GPIO, ADS_START_PORT);
	GPIO_PinInit(GPIO, ADS_START_PORT, ADS_START_PIN, &start_config);
	GPIO_PinWrite(GPIO, ADS_START_PORT, ADS_START_PIN, 0);
    
    PRINTF("\r\n\r\n%s\r\n",__FUNCTION__);
}


void ecg_start_set(void)
{
    GPIO_PinWrite(GPIO, ADS_START_PORT, ADS_START_PIN, 1);
}


void ecg_start_clr(void)
{
    GPIO_PinWrite(GPIO, ADS_START_PORT, ADS_START_PIN, 0);
}


void ecg_reset_set(void)
{
    GPIO_PinWrite(GPIO, ADS_RESET_PORT, ADS_RESET_PIN, 1);
}


void ecg_reset_clr(void)
{
    GPIO_PinWrite(GPIO, ADS_RESET_PORT, ADS_RESET_PIN, 0);
}


void ecg_spi_cs_set(void)
{
    GPIO_PinWrite(GPIO, ADS_CS_PORT, ADS_CS_PIN, 1);
}


void ecg_spi_cs_clr(void)
{
    GPIO_PinWrite(GPIO, ADS_CS_PORT, ADS_CS_PIN, 0);
}


void Init_Ecg_Spi(void)
{
	spi_master_config_t userConfig = {0};
	uint32_t srcFreq = 0;
	uint32_t i = 0;
	uint32_t err = 0;
	spi_transfer_t xfer = {0};
  
    CLOCK_AttachClk(kMAIN_CLK_to_FLEXCOMM3);
    //CLOCK_AttachClk(kFRO12M_to_FLEXCOMM3);
    RESET_PeripheralReset(kFC3_RST_SHIFT_RSTn);
    
	/*
	 * userConfig.enableLoopback = false;
	 * userConfig.enableMaster = true;
	 * userConfig.polarity = kSPI_ClockPolarityActiveHigh;
	 * userConfig.phase = kSPI_ClockPhaseFirstEdge;
	 * userConfig.direction = kSPI_MsbFirst;
	 * userConfig.baudRate_Bps = 500000U;
	 */
	SPI_MasterGetDefaultConfig(&userConfig);
	userConfig.polarity = kSPI_ClockPolarityActiveHigh;
	userConfig.phase = kSPI_ClockPhaseSecondEdge;
    
    //8M  max 12M
	userConfig.baudRate_Bps = 12000000U;
	srcFreq = ADS_SPI_MASTER_CLK_FREQ;
	userConfig.sselNum = (spi_ssel_t)ADS_SPI_SSEL;
	userConfig.sselPol = (spi_spol_t)ADS_SPI_SPOL;
	SPI_MasterInit(ADS_SPI_MASTER, &userConfig, srcFreq);
    
    PRINTF("%s\r\n",__FUNCTION__);
}


unsigned char ecg_spi_txrx8bit(unsigned char data)
{
	spi_transfer_t xfer = {0};
	unsigned char destBuff;
	xfer.txData = &data;
	xfer.rxData = &destBuff;
	xfer.dataSize = sizeof(destBuff);
	xfer.configFlags = kSPI_FrameAssert;
	SPI_MasterTransferBlocking(ADS_SPI_MASTER, &xfer);
	return destBuff;
}

void ecg_spi_read_buf(uint8_t *tx_buf,uint8_t *rx_buf,uint32_t len)
{
	spi_transfer_t xfer = {0};
    
	xfer.txData = tx_buf;
	xfer.rxData = rx_buf;
	xfer.dataSize = len;
	xfer.configFlags = kSPI_FrameAssert;
	SPI_MasterTransferBlocking(ADS_SPI_MASTER, &xfer);
}

void example_dma_test(void)
{
    uint8_t hello = 0x05;
    uint8_t read_data = 0;
    Init_Ecg_Spi();
    ads_spi_dma_init();
    ecg_spi_dma_read_buf(&hello,&read_data,1);
    //ecg_spi_txrx8bit(hello);
}
